#!/usr/bin/python
'''
Created by Colin Gillespie <c.gillespie@ncl.ac.uk>
$LastChangedDate$

'''

__revision__ = '$Rev$'

from Factorial import binomialM
from mrange import mrange
from swiginac import numeric
import ClosureMethods as CM


def closeMoment(tup):
    '''Closes a moment by converting to cumulant and back again'''
    
    if sum(tup) == 0:
        return numeric(1)
    if sum(tup) == 1:
        return CM.ClosureVariables().getMoment(tup)
    
    tup_list = list(tup)
    tup_list_rev = list(tup)
    tup_list_rev.reverse()

    for i, value in enumerate(tup_list_rev):
        if value != 0:
            tup_list[-i-1] = tup_list[-i-1] - 1
            break

    value = numeric(0)

    for i_tup in mrange(tup_list):
        r_i_diff = tuple([r-i for r, i in zip(tup, i_tup)])
        inner = binomialM(tuple(tup_list), i_tup)
        inner *= CM.ClosureVariables().getMoment(r_i_diff, moment=False)
        inner *= CM.ClosureVariables().getMoment(i_tup)
        value += inner

    return value.expand()

def closeMomentAsCumulant(tup):
    '''Closes a moment by converting to cumulant and back again'''
    
    if sum(tup) == 0:
        return numeric(1)
    if sum(tup) == 1:
        return CM.ClosureVariables().getCumulant(tup, moment=False)
    
    tup_list = list(tup)
    tup_list_rev = list(tup)
    tup_list_rev.reverse()

    for i, value in enumerate(tup_list_rev):
        if value != 0:
            tup_list[-i-1] = tup_list[-i-1] - 1
            break

    value = numeric(0)
    for i_tup in mrange(tup_list):
        r_i_diff = tuple([r-i for r, i in zip(tup, i_tup)])
        inner = binomialM(tuple(tup_list), i_tup)
        inner *= CM.ClosureVariables().getCumulant(r_i_diff, moment=False)
        inner *= CM.ClosureVariables().getCumulant(i_tup)
        value += inner

    return value.expand()

def cumulant2Moment(tup):
    
    if sum(tup) == 0:
        return numeric(0)
    if sum(tup) == 1:
        return CM.ClosureVariables().getMoment(tup)
    
    tup_list = list(tup)
    tup_list_rev = list(tup)
    tup_list_rev.reverse()

    for i, value in enumerate(tup_list_rev):
        if value != 0:
            tup_list[-i-1] = tup_list[-i-1] - 1
            break

    total = numeric(0)
    for i_tup in mrange(tup_list):
        r_i_diff = tuple([r-i for r, i in zip(tup, i_tup)])
        inner = binomialM(tuple(tup_list), i_tup)
        inner *= CM.ClosureVariables().getMoment(r_i_diff)
        inner *= CM.MomentStar().get(i_tup)

        total += inner
    return total.expand()     
 


def getMomentStar(tup):
    if sum(tup) == 0:
        return numeric(1)
    if sum(tup) == 1:
        CM.MomentStar().put(tup, -CM.ClosureVariables().getMoment(tup))
        return CM.MomentStar().get(tup)
    
    tup_list = list(tup)
    tup_list_rev = list(tup)
    tup_list_rev.reverse()

    for i, value in enumerate(tup_list_rev):
        if value != 0:
            tup_list[-i-1] = tup_list[-i-1] - 1
            break
    

    
    total = numeric(0)
    for i_tup in mrange(tup_list):
        r_i_diff = tuple([r-i for r, i in zip(tup, i_tup)])
        inner = binomialM(tuple(tup_list), i_tup)
        inner *= -numeric(1)*CM.ClosureVariables().getMoment(r_i_diff, moment=False)
        inner *= CM.MomentStar().get(i_tup)
        total += inner
    
    CM.MomentStar().put(tup, total)
    return total.expand()


if __name__ == '__main__':
    print closeMomentAsCumulant((3,))
    
    
    
    
    
    
    
